package com.scs.application.modules.sys.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.scs.application.core.consts.Const;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.query.QueryContext;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.service.IBaseFileService;
import com.scs.application.core.utils.FileUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.sys.entity.SerialRule;
import com.scs.application.modules.sys.mapper.SerialRuleMapper;
import com.scs.application.modules.sys.service.SerialOwnerService;
import com.scs.application.modules.sys.service.SerialRuleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description:编号规则文件处理类
 */
@Slf4j
@Service
public class FileSerialRuleServiceImpl extends BaseServiceImpl<SerialRuleMapper, SerialRule> implements SerialRuleService, IBaseFileService<SerialRule, SerialRule> {

    @Autowired
    @Lazy
    private SerialOwnerService serialOwnerService;

    @Override
    public List<String> batchGenerateCode(SerialRule serialRule, String target, int count) {
        return serialOwnerService.batchGenerateCode(serialRule, target, count);
    }

    @Override
    public SerialRule getSerialRule(String ruleCode) {
        SerialRule serialRule = new SerialRule();
        setSerialRule(serialRule, Const.getSerialRuleSrc() + ruleCode + ".json");
        if (serialRule == null) {
            throw new BusinessException("编号规则[" + ruleCode + "]未找到，请确认是否配置");
        }
        return serialRule;
    }

    @Override
    public boolean removeCascadeById(Serializable id) {
        List<SerialRule> serialRules = list();
        for (SerialRule serialRule : serialRules) {
            if (id.equals(serialRule.getId())) {
                FileUtils.deleteFile(Const.DATA_VIEW_SERIAL_RULE_SRC + serialRule.getCode() + ".json");
                break;
            }
        }
        return true;
    }

    @Override
    public SerialRule getById(Serializable id) {
        SerialRule serialRule = null;
        List<SerialRule> serialRules = list();
        for (SerialRule rule : serialRules) {
            if (id.equals(rule.getId())) {
                serialRule = rule;
                break;
            }
        }
        return serialRule;
    }

    @Override
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {
        List<SerialRule> serialRules = list();
        for (SerialRule serialRule : serialRules) {
            if (idList.contains(serialRule.getId())) {
                FileUtils.deleteFile(Const.DATA_VIEW_SERIAL_RULE_SRC + serialRule.getCode() + ".json");
            }
        }
        return true;
    }

    @Override
    public Page<SerialRule> page(QueryContext context) {
        List<SerialRule> serialRules = list(context);
        return filePage(context, serialRules);
    }

    @Override
    public List<SerialRule> list() {
        QueryContext context = new QueryContext();
        return list(context);
    }

    @Override
    public List<SerialRule> list(QueryContext context) {
        List<SerialRule> serialRules = getDTOList(Const.getSerialRuleSrc());
        if (context != null && context.getParams() != null) {
            String code = context.getParams().get("code") != null ? context.getParams().get("code").toString() : "";
            serialRules = serialRules.stream().filter(serialRule -> (StringUtils.isNotBlank(code) ? serialRule.getCode().indexOf(code) > -1 : true)).collect(Collectors.toList());
        }
        return serialRules;
    }

    @Override
    public SerialRule getDTO(String fileSrc) {
        SerialRule serialRule = new SerialRule();
        setSerialRule(serialRule, fileSrc);
        if (StringUtils.isBlank(serialRule.getCode()) || StringUtils.isBlank(serialRule.getId())) {
            return null;
        }
        return serialRule;
    }

    @Override
    public <SerialRule> boolean saveBatch(Class<SerialRule> modelClass, Collection<SerialRule> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean saveOrUpdate(SerialRule entity) {
        List<SerialRule> serialRules = list();
        if (entity.getId() == null) {
            entity.setId(StringUtils.getIdStr());
        } else {
            serialRules.stream().filter(serialRule -> entity.getCode().equalsIgnoreCase(serialRule.getCode())
                    && !entity.getId().equalsIgnoreCase(serialRule.getId())).findAny().ifPresent(serialRule -> {
                throw new BusinessException("Key已经存在，请重新命名！");
            });
        }
        File path = new File(Const.DATA_VIEW_SERIAL_RULE_SRC);
        if (!path.exists()) {
            path.mkdirs();
        }

        String fileNameWithPath = Const.DATA_VIEW_SERIAL_RULE_SRC + entity.getCode() + ".json";

        SerialRule serialRule = getById(entity.getId());
        if (serialRule == null) {
            serialRule = new SerialRule();
        } else if (!serialRule.getCode().equalsIgnoreCase(entity.getCode())) { //如果CODE发生变化，删除旧的JSON数据
            FileUtils.deleteFile(Const.DATA_VIEW_SERIAL_RULE_SRC + serialRule.getCode() + ".json");
        }
        com.scs.application.core.utils.BeanUtils.copyProperties(entity, serialRule);
        String result = JSON.toJSONString(serialRule, SerializerFeature.PrettyFormat);
        FileUtils.writeTxtFile(fileNameWithPath, result);
        return true;
    }

    private void setSerialRule(SerialRule serialRule, String fileNameWithPath) {
        String dataViewString = FileUtils.readFileStore(fileNameWithPath);
        if (StringUtils.isEmpty(dataViewString)) {
            return;
        }
        JSONObject jsonObject = JSONObject.parseObject(dataViewString);
        serialRule.setCode(jsonObject.getString("code"))
                .setDelimiter(jsonObject.getString("delimiter"))
                .setName(jsonObject.getString("name"))
                .setPartNum(jsonObject.getInteger("partNum"))
                .setPart1(jsonObject.getString("part1"))
                .setPart1Cond(jsonObject.getString("part1Cond"))
                .setPart2(jsonObject.getString("part2"))
                .setPart2Cond(jsonObject.getString("part2Cond"))
                .setPart3(jsonObject.getString("part3"))
                .setPart3Cond(jsonObject.getString("part3Cond"))
                .setPart4(jsonObject.getString("part4"))
                .setPart4Cond(jsonObject.getString("part4Cond"))
                .setId(jsonObject.getString("id"));
    }

    @Override
    public Boolean isSupport(Boolean flagProject) {
        return !flagProject;
    }
}
